package com.example.gatewaytest.ccb;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ccb.govpay.sign.SHA256withRSA;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author JiangMing Zhou
 * @date 2023/10/17 13:46
 * @jdk 1.8
 */
@Data
@Slf4j
public class CcbDecrypt {
    private String clientPrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCTElUMqAOEMZL84IEOaoPUXmPzLN6KaYSZoWPPfD6g7q9QOkn5sZ6w42wrRR7W207IUGbTHUhFGYklZNMv01I2b5/w/We21mJFJ1YiA6NfDFm9qyd0M31xQCuKUgY82GkvGQdpmTO/Kb8Yo89uv+nnKz+IUWNmzEZMnmTzgqcrzfILnTdMaovB46nbj+CElk7zSU8fdk1NBSqZXgmh1N1G+Ksls8BkGhzaVSSLNhfg2K0CoIOddcU3wlP0La0k43LqzwlGy5cLtjr6R99dPFSd7ZQC+7CTIEm0yyIfdrfzKP1X08tuCA5JP2ClQbshLB7Y8ZZqZizHT+0klHxq9SfDAgMBAAECggEBAIjdjZJ6pNMXw19bmh6NV2OB9+fswKj0a3cBLz5+tFXV6gZySDd7aV/aNObLq1htvRJDaH1dCc1sZyoKe1JNiXupQ6HkYOlQ9yC967U5x4aDmtwcdFn6NOn4usw9axqilrhCxZgq/3IN6o2GnFrHdGgx4iz8+NFIlr9kxDOtSd9DlMuuXjn5WaiTWj/1e+v7hXE1SAFSbjl6oAdUBGvM7GlU8/3yt5iC5KB1G3y2caihXFu201H/+POUssxlZRJuri2WA86XgGtvxuOv0LWG16lxg8658ahGO1dobKbuH9R6oqjO0SSDJr1fK6oYy0hbpm5e5vS5clkclWNK0c6HoDkCgYEA9RMHvtfWdK5HkdCKnvdIwmwNvhJgxd0nTnOSbi2P+LBP22j0Vu+QsrxNVVDRRxcTM+rykbW5TKd6CrMTLxKoj1Fdd1xGUoypJ5brRBJOKq5Nc7wSGmbDE9VWFBB0aFuD+IBSzyrYb4XqOjSVYhhVFyxiEk8CMdRspJfe4bzSuAUCgYEAmaDSgrmlQ3lAauMqpc+bzyOgr+mict2Sk3fvg3ZP1KZNSLrin07TF59viJoiZsn39MVYXMcndwIaR7rwTTjAV1OykPgYC4DRQHzzaGJd4hLyT8h107LyxKj2XcrdKPgFXPDZtSwtq+YgOmtD1DizK/tvHDIfVZuWxhv9S/aj0ycCgYEApFyD+FEnKg/sPfXf0idEa+gt+0i2EF12zB2kmjICeaY9mIg2PsvifozdTJesE4J9RXeQAXsf8DHuHpjlB8/6rkvCZJfFLf3aQIvt8zRXqjZGCZWbiotaz8VnOoOino6p3pKpdvlkOL9WTH0Rpr1s6+K/T0ofza2Kw4R7XWfW5sUCgYAi4E2p+7c28CndmiCub8kxZyctiF6msQJ7k/i94XgSEIbvAe48uEpXzIwneMZii2tNGBgNR/D/pWyN6DRxc3bG3GtnWcsroVzfxP4FLn+duStlTV7iZneSicEUXd+DU3r0NIFYDeV4Zs/eM0e8v/p8+6GnxwEyEBZUdzozqpRadQKBgQCPbyoLGByDK2bQo7se38lyRvDzewe6QPCByS2HQ3+9y9/O/vMhWIgAhhaQWOS5uDrglJFEc+F5fXBvThwaJXxK7nAIHq06Re2vFfpvAioDjz1xpmBchzcIU+pXhHLBkOiVmZLQfPQgl6qIRkZszF/fiwkbkOnZ4zRFd23yVA5LxA==";

    private String platformPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkxJVDKgDhDGS/OCBDmqD1F5j8yzeimmEmaFjz3w+oO6vUDpJ+bGesONsK0Ue1ttOyFBm0x1IRRmJJWTTL9NSNm+f8P1nttZiRSdWIgOjXwxZvasndDN9cUArilIGPNhpLxkHaZkzvym/GKPPbr/p5ys/iFFjZsxGTJ5k84KnK83yC503TGqLweOp24/ghJZO80lPH3ZNTQUqmV4JodTdRvirJbPAZBoc2lUkizYX4NitAqCDnXXFN8JT9C2tJONy6s8JRsuXC7Y6+kffXTxUne2UAvuwkyBJtMsiH3a38yj9V9PLbggOST9gpUG7ISwe2PGWamYsx0/tJJR8avUnwwIDAQAB";

    public CcbDecrypt() {
    }

    public String decryptBody(String body) {
        JSONObject jsonObject = JSON.parseObject(body);
        byte[] aesKey = decryptAesKey(jsonObject.getString("Tprt_Parm"));
        AES aes = SecureUtil.aes(aesKey);
        String bsnData = aes.decrypt(jsonObject.getString("Bsn_Data")).toString();
        Map<String, Object> data = JSONObject.parseObject(bsnData, Map.class);
        Set<String> listKey = getListKey(data);
        String sign = createSign(bsnData, listKey);
        boolean verified = SHA256withRSA.verifySign(platformPublicKey, sign, data.get("SIGN_INF").toString());
        if (!verified) {
            log.error("验签失败");
        }
        data.remove("SIGN_INF");
        return JSONObject.toJSONString(data);
    }

    public byte[] decryptAesKey(String aesKey) {
        RSA rsa = new RSA(clientPrivateKey, null);
        return rsa.decrypt(aesKey.getBytes(StandardCharsets.UTF_8), KeyType.PrivateKey);
    }

    public Set<String> getListKey(Map<String, Object> businessData) {
        Set<String> listKeySet = new HashSet<>();
        businessData.keySet().forEach(k -> {
            if (businessData.get(k) instanceof List) {
                listKeySet.add(k);
            }
        });
        return listKeySet;
    }

    /**
     * 拼接原串
     */
    @SuppressWarnings("rawtypes")
    private String splicingSign(String characterEncoding, SortedMap<String, Object> parameters, Set<String> set) {
        StringBuffer sbuffer = new StringBuffer();
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (set.contains(k)) {
                sbuffer.append(v);
            } else {
                if (!k.equals("SIGN_INF")
                        && !k.equals("Svc_Rsp_St")
                        && !k.equals("Svc_Rsp_CD")
                        && !k.equals("Rsp_Inf")
                ) {
                    sbuffer.append(k + "=" + v + "&");
                }
            }
        }
        return sbuffer.toString();
    }


    /**
     * 生成原串
     */
    private String createSign(String json, Set<String> set) {
        SortedMap<String, Object> sortedMap = new TreeMap<String, Object>();
        //转换JSON对象
        JSONObject jsonObject = JSONObject.parseObject(json);
        //遍历循坏外字段
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {

            if (null != entry.getValue()
                    && !"".equals(entry.getValue())
                    && !set.contains(entry.getKey())) {
                sortedMap.put(entry.getKey(), entry.getValue());
            }
        }
        if (!set.isEmpty()) {
            //处理集合字段
            Iterator<String> it = set.iterator();
            while (it.hasNext()) {
                String listKey = it.next();
                //System.out.println("List Key---------" + listKey);

                String listValue = processingSet(jsonObject, listKey);
                sortedMap.put(listKey, listValue);
            }
        }
        //字段拼接
        String sign = splicingSign("UTF-8", sortedMap, set);
        sign = sign.substring(0, sign.length() - 1);
        System.out.println("生成原串:" + sign);
        return sign;
    }


    /**
     * 处理集合内字段
     */
    private String processingSet(JSONObject jsonObj, String listKey) {
        SortedMap<String, Object> sortedMap = null;
        Set<String> set = new HashSet<String>();
        //返回拼接的原串
        StringBuffer sbuffer = new StringBuffer();
        //根据key获取集合json字符串
        String list = jsonObj.getString(listKey);
        //System.out.println("获取List json字符串----------" + list);
        if (list != null && list != "") {
            //list转换对象
            JSONArray jarr = JSONArray.parseArray(list);
            //创建json集合
            List<JSONObject> jsonValues = new ArrayList<JSONObject>();
            for (int i = 0; i < jarr.size(); i++) {
                jsonValues.add(jarr.getJSONObject(i));
            }
            //将json集合按照SN排序
            Collections.sort(jsonValues, new Comparator<JSONObject>() {
                public int compare(JSONObject a, JSONObject b) {
                    String valA = a.getString("SN");
                    String valB = b.getString("SN");
                    return valA.compareTo(valB);
                }
            });

            //暂存每一个子元素拼接的值
            String s = "";
            //遍历排序后的集合
            for (JSONObject j : jsonValues) {
                sortedMap = new TreeMap<String, Object>();
                for (Map.Entry<String, Object> entry : j.entrySet()) {
                    if (null != entry.getValue() && !"".equals(entry.getValue())) {

                        sortedMap.put(entry.getKey(), entry.getValue());
                    }
                }
                s = splicingSign("UTF-8", sortedMap, set);
                sbuffer.append(s);
            }
            return sbuffer.toString();
        }
        return sbuffer.toString();
    }
}
